// ----------------------------------------
// Filename: TSensor.c
// Description: Routines to implement an I2C Temperature Sensor
// Author: Anton Jatmiko
// Date: 20 April 2014

#include "TSensor.h"

static const UINT8 SlaveAddressWrite = 0x92;    // Address of temp sensor followed by write
static const UINT8 SlaveAddressRead = 0x93;     // Address of temp sensor followed by read
static const UINT8 PtrTempReg = 0x00;           // Pointer reg of temp reg
static const UINT8 PtrConfReg = 0x01;           // Pointer reg of conf reg
static const UINT8 PtrThystReg = 0x02;          // Pointer reg of hysteresis reg
static const UINT8 PtrTosReg = 0x03;            // Pointer reg of overtemperature shutdown reg
static const UINT8 ConfBit = 0x0C;              // queue: 2, OS: active low, OS Comparator, Normal Mode
static const UINT8 TosMSB = 0x64;               // Shutdown at 100 deg C
static const UINT8 TosLSB = 0x00;
static const UINT8 ThystMSB = 0x60;             // Restart at 96 deg C
static const UINT8 ThystLSB = 0x00;

TINT32 TSensor_MilliCelc;
static UINT8 ReadState = 0;

// ----------------------------------------
// TSensor_Init
//
// Initialize temperature sensor
// Input:
//   none
// Output:
//   none
// Conditions:
//   none
void TSensor_Init(void)
{
    TUINT16 dummyVar;

    I2C_Init();
    TRISDbits.RD6 = 1;                          // Set OS pin to input

    __delay_ms(5);

    // Set config bits
    while (!I2C_Start());                       // Start transmit
    while (!I2C_Transmit(SlaveAddressWrite));   // Send slave address write
    while (!I2C_Transmit(PtrConfReg));          // Send config pointer
    while (!I2C_Transmit(ConfBit));             // Send config data


    while (!I2C_Stop());                        // Stop config

//    // Set Tos
//    while (!I2C_Start());                       // Start transmit
//    while (!I2C_Transmit(SlaveAddressWrite));   // Send slave address write
//    while (!I2C_Transmit(PtrTosReg));           // Send Tos pointer
//    while (!I2C_Transmit(TosMSB));              // Send Tos MSB
//    while (!I2C_Transmit(TosLSB));              // Send Tos LSB
//    while (!I2C_Stop());                        // Stop trasmit
//
//    // Set Thyst
//    while (!I2C_Start());                       // Start transmit
//    while (!I2C_Transmit(SlaveAddressWrite));   // Send slave address write
//    while (!I2C_Transmit(PtrThystReg));         // Send Thyst pointer
//    while (!I2C_Transmit(ThystMSB));            // Send Thyst MSB
//    while (!I2C_Transmit(ThystLSB));            // Send Thyst LSB
//    while (!I2C_Stop());                        // Stop transmit
//
//    // Preset Temp Reg Pointer
//    while (!I2C_Start());                       // Start transmit
//    while (!I2C_Transmit(SlaveAddressWrite));   // Send slave address write
//    while (!I2C_Transmit(PtrTempReg));          // Send temp reg pointer
//    while (!I2C_Restart());                     // Send restart
//    while (!I2C_Transmit(SlaveAddressRead));    // Send slave address read
//    while (!I2C_Receive(&dummyVar.s.Hi));       // Reveice MSB
//    while (!I2C_ACK());                         // Send ACK
//    while (!I2C_Receive(&dummyVar.s.Lo));       // Receive LSB
//    while (!I2C_NAK());                         // Send NAK
//    while (!I2C_Stop());                        // Stop Receive
}

// ----------------------------------------
// TSensor_ReadStarted
//
// Start reading temperature value from the sensor
// Input:
//   start is a boolean indicating whether to start or stop the reading
// Output:
//   TRUE if read is started successfully
// Conditions:
//   assume temperature register has been read or preset
BOOL TSensor_ReadStarted(BOOL start)
{
    if (start && (ReadState == 0))
    {
        if (LATDbits.LD6 && I2C_Start())
        {
            ++ReadState;
            LATBbits.LB5 = 1;           // Turn on LED
            return bTRUE;
        }
    }

    return bFALSE;
}

// ----------------------------------------
// TSensor_ReadExecuting
//
// Start reading temperature value from the sensor
// Input:
//   readStarted is a boolean indicating whether or not read has been started
//   dataObtained is a pointer to data obtained flag
//   dataMSB is a pointer to the MSB temperature value
//   dataLSB is a pointer to the LSB temperature value
// Output:
//   TRUE if read is still in progress
// Conditions:
//   assume temperature register has been read or preset
BOOL TSensor_ReadExecuting(BOOL readStarted, BOOL * const dataObtainedPtr, UINT8 * const dataMSBPtr, UINT8 * const dataLSBPtr)
{
    if (LATDbits.LD6 && readStarted)
    {
        switch (ReadState)
        {
            case 1: if (I2C_Transmit(SlaveAddressRead))
                        ++ReadState;
                    break;
            case 2: if (I2C_Receive(dataMSBPtr))
                        ++ReadState;
                    break;
            case 3: if (I2C_ACK())
                        ++ReadState;
                    break;
            case 4: if (I2C_Receive(dataLSBPtr))
                        ++ReadState;
                    break;
            case 5: if (I2C_NAK())
                        ++ReadState;
                    break;
            case 6: if (I2C_Stop())
                        ++ReadState;
                    break;
            case 7: if (!I2C_Busy())
                    {
                        ReadState = 0;
                        *dataObtainedPtr = 1;      // Data has been obtained
                        LATBbits.LB5 = 0;       // Turn off LED
                        return bFALSE;
                    }
                    break;
            default:    break;
        }
    }
    else if (!LATDbits.LD6)
    {
        ReadState = 0;
        *dataObtainedPtr = 0;      // Data has not been obtained
        LATBbits.LB5 = 0;       // Turn off LED
        return bFALSE;
    }

    return readStarted;
}

// ----------------------------------------
// TSensor_ReadExecuting
//
// Convert the raw data to milli Celcius
// Input:
//   rawData is the data read from the sensor
//   dataObtained is a pointer to data obtained flag
// Output:
//   temperature value in milli Celcius
// Conditions:
//   none
INT32 TSensor_Raw2MilliCelc(TUINT16 rawData, BOOL * const dataObtainedPtr)
{
    TINT32 milliCelc;
    milliCelc.l = (INT32) ((rawData.l & 0x7FFF) >> 5) * 125;
    milliCelc.s.Hi = (rawData.l & 0x8000);
    *dataObtainedPtr = 0;
    return milliCelc.l;
}